Skip to content

Add virtual output support#3800

Open
willybarret wants to merge 4 commits intoniri-wm:mainfrom
willybarret:wip/virtual-outputs
Open

Add virtual output support#3800
willybarret wants to merge 4 commits intoniri-wm:mainfrom
willybarret:wip/virtual-outputs

Conversation

@willybarret
Copy link
Copy Markdown

I noticed there has been significant interest in virtual output support (discussed in #714 and #3101), so I'd like to share this implementation I've been working on :)

I took some inspiration from Sway's headless output approach (as mentioned in #3101) for certain parts. The feature supports both the headless backend (running niri with no physical monitor at all) and the TTY backend (creating virtual outputs alongside physical displays) , and outputs can be created, removed, and configured via IPC or config.kdl.

Some of the use cases, which were brought up in those discussions are: Sunshine/Moonlight streaming via wlr-screencopy, VNC with tools like wayvnc, headless remote sessions over SSH, and concurrent independent streaming sessions.

The video below shows two independent users, each running their own niri headless session and Sunshine instance, with multiple virtual outputs created per session. I've also opened a PR to Sunshine (LizardByte/Sunshine#4954) that enables input isolation between concurrent Sunshine instances, which makes this setup fully usable :)

Please test and report any issues or suggestions

virtual-outputs.mp4

- Introduced `CreateVirtualOutput` and `RemoveVirtualOutput` requests in IPC.
- Implemented corresponding message handling in the client.
- Added methods for creating and removing virtual outputs in the backend.
- Updated CLI to support virtual output creation and removal commands.
- Added documentation for virtual outputs in the wiki.
…ut integration

- Introduced support for virtual outputs in the headless backend, allowing for dynamic creation and removal of outputs.
- Implemented a new `VirtualOutputMarker` to identify virtual outputs and manage their state.
- Added functionality to apply configuration changes to managed virtual outputs based on the provided config.
- Integrated libinput plugin system initialization for headless backend, enabling input handling.
- Enhanced rendering logic to accommodate virtual outputs, ensuring proper frame callback delivery.
- Refactored existing code to improve modularity and maintainability, including the extraction of libinput plugin initialization into a separate module.
- Updated the TTY backend to mirror virtual outputs and handle IPC communication for them.
@Sempyos Sempyos added area:output Monitors, scaling, VRR, DPMS area:config Config parsing, default config, new settings area:ipc niri msg, niri IPC, D-Bus, scripting pr kind:feature New features and functionality labels Apr 10, 2026
@bczhc
Copy link
Copy Markdown

bczhc commented Apr 11, 2026

This is cool and very useful! Before, I'm using say niri msg action set-window-height 10000 to make one window very tall and then niri msg action screenshot-window takes the long screenshot of it. With this, i'm able to create a large virtual display and put things into it then do screenshots, which is useful. Virtual outputs previewing approach for me is vncviewer + wayvnc (since for unknown reason I haven't managed to make my sunshine work under Wayland). okay wl-mirror is the better way.

One thing is, could the virtual output name can be specified or fixed? Since the virtual output is created only when I need it. A creating-removing-creating will produce a different incremented name thus output "HEADLESS-n" in the config will not be valid anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:config Config parsing, default config, new settings area:ipc niri msg, niri IPC, D-Bus, scripting area:output Monitors, scaling, VRR, DPMS pr kind:feature New features and functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants